package com.stars.easyms.datasource.mybatisplus.service;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.stars.easyms.datasource.EasyMsDataSourceFactory;
import com.stars.easyms.datasource.transaction.EasyMsTransactionStatusHolder;
import com.stars.easyms.datasource.transaction.EasyMsTransactionSynchronizationManager;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.MyBatisExceptionTranslator;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.Objects;
import java.util.function.Consumer;

/**
 * <p>className: EasyMsServiceImpl</p>
 * <p>description: EasyMs自定义service实现类</p>
 *
 * @author guoguifang
 * @version 1.7.3
 * @date 2021/3/29 10:00 上午
 */
public class EasyMsServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {

    @Override
    protected boolean executeBatch(Consumer<SqlSession> consumer) {
        boolean transaction = TransactionSynchronizationManager.isSynchronizationActive();
        if (transaction) {
            SqlSessionFactory sqlSessionFactory = SqlHelper.sqlSessionFactory(entityClass);
            EasyMsTransactionStatusHolder easyMsTransactionStatusHolder = EasyMsTransactionSynchronizationManager.newTransactionStatusHolder(
                    EasyMsDataSourceFactory.getEasyMsMultiDataSource().getCurrentDataSource());
            SqlSession sqlSession = easyMsTransactionStatusHolder.getSqlSessionHolder().getSqlSession(sqlSessionFactory);
            try {
                consumer.accept(sqlSession);
                return true;
            } catch (Throwable t) {
                Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
                if (unwrapped instanceof RuntimeException) {
                    MyBatisExceptionTranslator myBatisExceptionTranslator
                            = new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true);
                    throw Objects.requireNonNull(myBatisExceptionTranslator.translateExceptionIfPossible((RuntimeException) unwrapped));
                }
                throw ExceptionUtils.mpe(unwrapped);
            }
        }
        return super.executeBatch(consumer);
    }

}
